/*
 * BasicIdeogramUI.java
 * Prakash Manandhar http://p-manandhar.info
 * Created Dec 24, 2010
 */

package ideogrammaker;

import java.awt.*;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;

/**
 * Basic Ideogram UI.
 * @author Prakash Manandhar
 */
public class BasicIdeogramUI extends IdeogramUI {

    private float scale;
    private float scale_value;
    private static final int border = 10;
    private static final int gap = 5;
    private static final int scale_bar_width = 5;
    private static final int bar_width = 20;
    private static final Font font = new Font("Times New Roman", Font.PLAIN, 20);
    private int current_x = border;
    private FontMetrics metrics;
    private int str_height;

    public static ComponentUI createUI(JComponent c) {
        return new BasicIdeogramUI();
    }

    public void installUI(JComponent c) {
        IdeogramComponent comp = (IdeogramComponent)c;
    }

    public void uninstallUI(JComponent c) {
        
    }

    public void paintGraphics (Graphics2D g, IdeogramData model,
            int width, int height) {
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                  RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        metrics = g.getFontMetrics(font);
        str_height = metrics.getHeight();
        // Do the rest of the painting
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);
        current_x = border;
        g.setFont(font);

        calculateScale(model, height);
        drawScaleBar((Graphics2D)g, width, height);
        drawChromosomes((Graphics2D)g, model, height);
    }

    public void paint (Graphics g, JComponent c) {
        IdeogramComponent ic = (IdeogramComponent)c;
        // We don't want to paint inside of the insets or
        // borders, so subtract them out.
        Insets insets = c.getInsets();
        Graphics2D g2d = (Graphics2D)g;
        
        g.translate(insets.left, insets.top);
        int width = c.getWidth()-insets.left-insets.right;
        int height = c.getHeight()-insets.top-insets.bottom;
        IdeogramData model = (IdeogramData)(ic.getModel());
        paintGraphics(g2d, model, width, height);
        g.translate(-insets.left, -insets.top);
    }

    private void calculateScale(IdeogramData m, int height) {
        int half_ht = (height/2-border -str_height - 4*gap);
        scale = Math.abs(half_ht/m.getMax());
        scale_value = 1;
        if (scale*scale_value > half_ht) {
            while(scale*scale_value > half_ht) scale_value /= 2;
        } else {
            while (scale_value*2*scale < half_ht) {
                scale_value *= 2;
            }
        }
        
        System.out.println("Calculating scale = " + scale
                              + ", value = " + scale_value);
    }

    private void drawScaleBar(Graphics2D g, int width, int height) {
        g.setColor(Color.BLACK);
        final int midy = (height-str_height)/2;
        
        g.rotate(-Math.PI/2);
        String scale_string = scale_value + "\u03bc";
        int str_width  = metrics.stringWidth(scale_string);
        
        g.drawString(scale_string, -(midy+str_width), current_x+str_height);
        current_x += str_height + 2*gap;
        g.rotate(Math.PI/2);
        g.setStroke(new BasicStroke(scale_bar_width, 
                BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        g.drawLine(current_x, midy+gap, current_x, midy+gap+(int)(scale*scale_value));
    }

    private void drawChromosomes(Graphics2D g, IdeogramData m, int height) {
        final int midy = (height-str_height)/2;
        g.setStroke(new BasicStroke(bar_width,
                BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        for (int i = 0; i < m.getRowCount(); i++) {
            current_x += 2*gap + bar_width;
            int start_y = midy + gap;
            int end_y   = start_y + (int)(scale*m.getFloatAt(i, 0));
            g.drawLine(current_x, start_y, current_x, end_y);
            start_y = end_y + gap;
            end_y = start_y + (int)(scale*m.getFloatAt(i, 1));
            g.drawLine(current_x, start_y, current_x, end_y);
            start_y = midy + (int)(m.getMax()*scale)
                      + 2*gap + str_height;
            g.drawString(new Integer(i+1).toString(), current_x-bar_width/3, start_y);

            start_y = midy - gap;
            end_y   = start_y - (int)(scale*m.getFloatAt(i, 2));
            g.drawLine(current_x, start_y, current_x, end_y);
            start_y = end_y - gap;
            end_y = start_y - (int)(scale*m.getFloatAt(i, 3));
            g.drawLine(current_x, start_y, current_x, end_y);

        }
    }

}
